
#include "asm/stx7200reg.h"
#include "../../../cpu/sh/init_ram.S"

/*
 * This is derived from STMicroelectronics gnu toolchain example:
 *   sh-superh-elf/examples/os21/romdynamic/memory_mb671.S
 */

/*
 * The poke table is a series of long words, in the format
 *
 *       opcode, address, operand, ...
 *
 * An opcode of 0 marks the table end
 */

#ifndef CONFIG_STM_NEW_POKE_TABLE_PARADIGM
/*
 * For compatibility with old poke table code, we define some of the
 * new names, to map onto the old names. Ultimately, the old poke table
 * code will be updated to the "new order", and we can just delete
 * the following mappings.
 */
#define POKE8(A, VAL)				POKE_CHAR(A, VAL)
#define POKE16(A, VAL)				POKE_SHORT(A, VAL)
#define POKE32(A, VAL)				POKE_LONG(A, VAL)
#define OR32(A, VAL)				OR_LONG(A, VAL)
#define UPDATE32(A, AND, OR)			UPDATE_LONG(A, AND, OR)
#define POKE_UPDATE32(A1, A2, AND, SHIFT, OR)	POKE_UPDATE_LONG(A1, A2, AND, SHIFT, OR)
#define WHILE_NE32(A, AND, VAL)			WHILE_NE(A, AND, VAL)
#define DELAY(VAL)				/* do nothing */
#endif /* CONFIG_STM_NEW_POKE_TABLE_PARADIGM */


	.section .data.init, "a"

	.balign 32

__memory_setup_table:

	/* ----- STx7200 Clocks ----- */

	/* Set CLOCKGENA PLL0 into BYPASS... */
	OR32(STX7200_CLOCKGENA_PLL0_CFG, 0x00100000)

	/* Power down CLOCKGENA PLL0... */
	OR32(STX7200_CLOCKGENA_POWER_CFG, 0x00000001)

	/* Configure CLOCKGENA PLL0... to 900MHz */
	UPDATE32(STX7200_CLOCKGENA_PLL0_CFG, 0xfff80000, 0x01 | (0x0f << 8))

	/* Enable CLOCKGENA PLL0... */
	UPDATE32(STX7200_CLOCKGENA_POWER_CFG, 0xfffffffe, 0)

	/* Wait for CLOCKGENA PLL0 to lock... */
	WHILE_NE32(STX7200_CLOCKGENA_PLL0_CFG, 0x80000000, 0x80000000)

	/* Clear CLOCKGENA PLL0 from BYPASS... */
	UPDATE32(STX7200_CLOCKGENA_PLL0_CFG, 0xffefffff, 0)

	/* Set CLOCKGENA PLL1 into BYPASS... */
	OR32(STX7200_CLOCKGENA_PLL1_CFG, 0x00100000)

	/* Power down CLOCKGENA PLL1... */
	OR32(STX7200_CLOCKGENA_POWER_CFG, 0x00000002)

	/* Configure CLOCKGENA PLL1... */
	UPDATE32(STX7200_CLOCKGENA_PLL1_CFG, 0xfff80000, 0x01 | (0x0f << 8))

	/* Enable CLOCKGENA PLL1... */
	UPDATE32(STX7200_CLOCKGENA_POWER_CFG, 0xfffffffd, 0)

	/* Wait for CLOCKGENA PLL1 to lock... */
	WHILE_NE32(STX7200_CLOCKGENA_PLL1_CFG, 0x80000000, 0x80000000)

	/* Clear CLOCKGENA PLL1 from BYPASS... */
	UPDATE32(STX7200_CLOCKGENA_PLL1_CFG, 0xffefffff, 0)

	/* Set CLOCKGENA PLL2 into BYPASS... */
	OR32(STX7200_CLOCKGENA_PLL2_CFG, 0x00100000)

	/* Power down CLOCKGENA PLL2... */
	OR32(STX7200_CLOCKGENA_POWER_CFG, 0x00000004)

	/* Configure CLOCKGENA PLL2... */
	UPDATE32(STX7200_CLOCKGENA_PLL2_CFG, 0xfff80000, 0x03 | (0x28 << 8) | (0x00 << 16))

	/* Enable CLOCKGENA PLL2... */
	UPDATE32(STX7200_CLOCKGENA_POWER_CFG, 0xfffffffb, 0)

	/* Wait for CLOCKGENA PLL2 to lock... */
	WHILE_NE32(STX7200_CLOCKGENA_PLL2_CFG, 0x80000000,  0x80000000)

	/* Clear CLOCKGENA PLL2 from BYPASS... */
	UPDATE32(STX7200_CLOCKGENA_PLL2_CFG, 0xffefffff, 0)

	/* Set CLOCKGENB PLL0 into BYPASS... */
	OR32(STX7200_CLOCKGENB_PLL0_CFG, 0x00100000)

	/* Power down CLOCKGENB PLL0... */
	OR32(STX7200_CLOCKGENB_POWER_CFG, 0x00008000)

	/* Configure CLOCKGENB PLL0... */
	UPDATE32(STX7200_CLOCKGENB_PLL0_CFG, 0xfff80000, 0x03 | (0x28 << 8) | (0x00 << 16))

	/* Enable CLOCKGENB PLL0... */
	UPDATE32(STX7200_CLOCKGENB_POWER_CFG, 0xffff7fff, 0)

	/* Wait for CLOCKGENB PLL0 to lock... */
	WHILE_NE32(STX7200_CLOCKGENB_PLL0_CFG, 0x80000000, 0x80000000)

	/* Clear CLOCKGENB PLL0 from BYPASS... */
	UPDATE32(STX7200_CLOCKGENB_PLL0_CFG, 0xffefffff, 0)

	/* Power down PLL... */
	OR32(STX7200_SYSCONF_SYS_CFG11, 0x00001000)

#ifdef SLOW_LMI
	/* Set LMI clock to 666MHz */
	UPDATE32(STX7200_SYSCONF_SYS_CFG11, 0xfffff001, (0x05 << 9) | (0x6f << 1))
#else	/* !SLOW_LMI */
	/* Set LMI clock to 800MHz */
	UPDATE32(STX7200_SYSCONF_SYS_CFG11, 0xfffff001, (0x03 << 9) | (0x50 << 1))
#endif	/* SLOW_LMI */

	/* Enable CLOCKGENA PLL1... */
	UPDATE32(STX7200_SYSCONF_SYS_CFG11, 0xffffefff, 0)

	/* Wait for CLOCKGENA PLL1 to lock... */
#ifdef CONFIG_STM_NEW_POKE_TABLE_PARADIGM
	IF_EQ32(1, STX7200_SYSCONF_DEVICEID_0, 0x0fffffff, 0x0d437041)
	  WHILE_NE32(STX7200_SYSCONF_SYS_STA03, 0x00000001, 1)
	ELSE(1)
	  /* On cut 1 polarity inverted on lock bit */
	  WHILE_NE32(STX7200_SYSCONF_SYS_STA03, 0x00000001, 0)
	ENDIF(1)
#else /* CONFIG_STM_NEW_POKE_TABLE_PARADIGM */
	IF_DEVID(STX7200_CUT1)
	  /* On cut 1 polarity inverted on lock bit */
	  WHILE_NE32(STX7200_SYSCONF_SYS_STA03, 0x00000001, 0)
	ENDIF
	IF_DEVID(STX7200_CUT2)
	  WHILE_NE32(STX7200_SYSCONF_SYS_STA03, 0x00000001, 1)
	ENDIF
#endif /* CONFIG_STM_NEW_POKE_TABLE_PARADIGM */

	/* ----- STx7200 Sysconf ----- */

	/* PLI_CLOCK_ENABLE set to 0 */
	UPDATE32(STX7200_SYSCONF_SYS_CFG58, ~(1 << 0), 0)

	/* LMI sub-sys & pl exit from reset */
	OR32(STX7200_SYSCONF_SYS_CFG11, 0x1 | (1 << 27))
	OR32(STX7200_SYSCONF_SYS_CFG15, 0x1 | (1 << 27))

	/* Delay ~ 200 uS (assumes 400MHz CPU clock) */
	DELAY(200 * 400)

	/* PLI_CLOCK_ENABLE set to 1 */
	OR32(STX7200_SYSCONF_SYS_CFG58, (1 << 0))

	/* Check both DLL on LMI0 are locked */
	WHILE_NE32(STX7200_SYSCONF_SYS_STA03, (1 << 10) | (1 << 20), (1 << 10) | (1 << 20))

	/* Check both DLL on LMI1 are locked */
	WHILE_NE32(STX7200_SYSCONF_SYS_STA05, (1 << 10) | (1 << 20), (1 << 10) | (1 << 20))

	/* Adjust proga, progb, zoutproga, and receiver mode for LMI0 */
	POKE32(STX7200_SYSCONF_SYS_CFG12, 0xa2007801 | (0x7 << 1) | (0x0 << 4) | (0x0 << 7) | (0x0 << 10))

	/* Adjust proga, progb, zoutproga, and receiver mode for LMI1 */
	POKE32(STX7200_SYSCONF_SYS_CFG16, 0xa2007801 | (0x7 << 1) | (0x0 << 4) | (0x0 << 7) | (0x0 << 10))

	/* Enable AutoPrecharge */
	POKE32(STX7200_SYSCONF_SYS_CFG38, 0x000ffd08)
	POKE32(STX7200_SYSCONF_SYS_CFG39, 0x000ffd18)

	/* Force DLL1 and DLL2 command of LMI0 */
	POKE32(STX7200_SYSCONF_SYS_CFG13, 0x00000002)
	POKE32(STX7200_SYSCONF_SYS_CFG14, 0x00000002)

	/* Force DLL1 and DLL2 command of LMI1 */
	POKE32(STX7200_SYSCONF_SYS_CFG17, 0x00000002)
	POKE32(STX7200_SYSCONF_SYS_CFG18, 0x00000002)

	/* Set cfg55 and cfg56 */
	POKE32(STX7200_SYSCONF_SYS_CFG55, 0x03fc2004 | (0 << 10) | (0x7 << 7))
	POKE32(STX7200_SYSCONF_SYS_CFG56, 0x03fc2004 | (0 << 10) | (0x7 << 7))

	/* PDL offsets
	 # -11=1F5 => 42=0x07D7EBF5, 43=0x000001F5
	 # -21=1EB => 42=0x07afd7eb, 43=0x000001eb
	 #sysconf.SYSCONF_CFG42.poke(0x07D7EBF5)
	 #sysconf.SYSCONF_CFG43.poke(0x000001F5)
	 */

	/* TO BE UPDATED FOR 7200/MB671 */
	POKE32(STX7200_SYSCONF_SYS_CFG42, 0x00000000)
	POKE32(STX7200_SYSCONF_SYS_CFG43, 0x00000000)

	POKE32(STX7200_SYSCONF_SYS_CFG44, 0x00000000)
	POKE32(STX7200_SYSCONF_SYS_CFG45, 0x00000000)

	/* ----- STx7200 EMI configuration ----- */

	POKE32(ST40_EMI_BANK_ENABLE, 0x00000005)

	/* NOTE: bits [0,5] define bottom address bits [22,27] of bank */
	POKE32(ST40_EMI_BANK0_BASEADDRESS, 0x00000000)
	POKE32(ST40_EMI_BANK1_BASEADDRESS, 0x00000008)
	POKE32(ST40_EMI_BANK2_BASEADDRESS, 0x0000000c)
	POKE32(ST40_EMI_BANK3_BASEADDRESS, 0x00000010)
	POKE32(ST40_EMI_BANK4_BASEADDRESS, 0x00000014)

	/* Bank 0 - On-board 32MiB Flash at address 0x00000000 -> 0x01ffffff */
	POKE32(ST40_EMI_BANK0_EMICONFIGDATA0, 0x001016d1)
	POKE32(ST40_EMI_BANK0_EMICONFIGDATA1, 0x9d200000)
	POKE32(ST40_EMI_BANK0_EMICONFIGDATA2, 0x9d220000)
	POKE32(ST40_EMI_BANK0_EMICONFIGDATA3, 0x00000000)

	/* Bank 1 - Not configured */
	/* Bank 2 - Not configured */
	/* Bank 3 - Not configured */
	/* Bank 4 - Not configured */

	/* Program other EMI registers */
	POKE32(ST40_EMI_GENCFG, 0x00000050)

	/* ----- STx7200 LMI0 configuration ----- */

	/* "Refresh Interval" is set equal to 0xA28=2600 => 2600*3ns=7.8us */
	POKE32(ST40_LMI_MIM_0(0), 0x07f6015b)
	POKE32(ST40_LMI_MIM_1(0), 0x000000b0)

	POKE32(ST40_LMI_STR_0(0), 0xcd2db41b)
	POKE32(ST40_LMI_STR_1(0), 0x002202d6)

	/* lmi base address 0x08000000 + 256MiB */
	POKE32(ST40_LMI_SDRA0_0(0), 0x18001a20)

	/* lmi base address 0x08000000 + 256MiB */
	POKE32(ST40_LMI_SDRA1_0(0), 0x18001a20)

	/* Delay ~ 200 uS (assumes 400MHz CPU clock) */
	DELAY(200 * 400)

	/* Enable clock with NOP command */
	POKE32(ST40_LMI_SCR_0(0), 0x00020021)
	POKE32(ST40_LMI_SCR_0(0), 0x00020023)
	/* Wait NOP command for 400 nsec */
	POKE32(ST40_LMI_SCR_0(0), 0x00020021)
	POKE32(ST40_LMI_SCR_0(0), 0x00020021)
	POKE32(ST40_LMI_SCR_0(0), 0x00020021)
	POKE32(ST40_LMI_SCR_0(0), 0x00020021)
	POKE32(ST40_LMI_SCR_0(0), 0x00020021)
	POKE32(ST40_LMI_SCR_0(0), 0x00020021)
	POKE32(ST40_LMI_SCR_0(0), 0x00020021)
	POKE32(ST40_LMI_SCR_0(0), 0x00020021)
	POKE32(ST40_LMI_SCR_0(0), 0x00020021)
	POKE32(ST40_LMI_SCR_0(0), 0x00020021)

	/* Precharge all */
	POKE32(ST40_LMI_SCR_0(0), 0x00020022)
	/* Wait NOP command for 400 nsec */
	POKE32(ST40_LMI_SCR_0(0), 0x00020021)
	POKE32(ST40_LMI_SCR_0(0), 0x00020021)
	POKE32(ST40_LMI_SCR_0(0), 0x00020021)
	POKE32(ST40_LMI_SCR_0(0), 0x00020021)
	POKE32(ST40_LMI_SCR_0(0), 0x00020021)
	POKE32(ST40_LMI_SCR_0(0), 0x00020021)
	POKE32(ST40_LMI_SCR_0(0), 0x00020021)
	POKE32(ST40_LMI_SCR_0(0), 0x00020021)
	POKE32(ST40_LMI_SCR_0(0), 0x00020021)

	/* Issue EMRS2 */
	POKE32(ST40_LMI_SDMR0(0), 0x00010000)

	/* Issue EMRS3 */
	POKE32(ST40_LMI_SDMR0(0), 0x00018000)

	/* Issue EMRS1 to enable DLL */
	POKE32(ST40_LMI_SDMR0(0), 0x00008004)

	/* Issue MRS with DLL reset, CAS 5, Write recovery 6, Sequentiel, Burst lengh 8 */
	POKE32(ST40_LMI_SDMR0(0), 0x00000b53)

	/* Wait NOP command for 400 nsec */
	POKE32(ST40_LMI_SCR_0(0), 0x00020021)
	POKE32(ST40_LMI_SCR_0(0), 0x00020021)
	POKE32(ST40_LMI_SCR_0(0), 0x00020021)
	POKE32(ST40_LMI_SCR_0(0), 0x00020021)
	POKE32(ST40_LMI_SCR_0(0), 0x00020021)
	POKE32(ST40_LMI_SCR_0(0), 0x00020021)
	POKE32(ST40_LMI_SCR_0(0), 0x00020021)
	POKE32(ST40_LMI_SCR_0(0), 0x00020021)
	POKE32(ST40_LMI_SCR_0(0), 0x00020021)
	POKE32(ST40_LMI_SCR_0(0), 0x00020021)

	/* Precharge all */
	POKE32(ST40_LMI_SCR_0(0), 0x00020022)
	/* 2 CBR (auto refresh) */
	POKE32(ST40_LMI_SCR_0(0), 0x00020024)
	POKE32(ST40_LMI_SCR_0(0), 0x00020024)

	/* Issue MRS with CAS 5, Write recovery 6, Sequentiel, Burst lengh 8 */
	POKE32(ST40_LMI_SDMR0(0), 0x00000a53)

	/* Enable auto refresh */
	POKE32(ST40_LMI_MIM_0(0), 0x07f6035b)
	POKE32(ST40_LMI_SCR_0(0), 0x00020021)
	POKE32(ST40_LMI_SCR_0(0), 0x00020021)
	POKE32(ST40_LMI_SCR_0(0), 0x00020021)
	POKE32(ST40_LMI_SCR_0(0), 0x00020021)

	POKE32(ST40_LMI_GCC_0(0), 0x00000000)

	/* ----- STx7200 LMI1 configuration ----- */

	POKE32(ST40_LMI_MIM_0(1), 0x07f6015b)
	POKE32(ST40_LMI_MIM_1(1), 0x000000b0)

	/* SDRAM Timing Register */
	POKE32(ST40_LMI_STR_0(1), 0xcd2db41b)
	POKE32(ST40_LMI_STR_1(1), 0x002202d6)

	/* SDRAM Row Attribute 0 */
	/* lmi base address 0x18000000 + 64MiB */
	POKE32(ST40_LMI_SDRA0_0(1), 0x1c001a20)

	/* SDRAM Row Attribute 1 */
	/* lmi base address 0x18000000 + 64MiB */
	POKE32(ST40_LMI_SDRA1_0(1), 0x1c001a20)

	/* Delay ~ 200 uS (assumes 400MHz CPU clock) */
	DELAY(200 * 400)

	/* Enable clock with NOP command */
	POKE32(ST40_LMI_SCR_0(1), 0x00020021)
	POKE32(ST40_LMI_SCR_0(1), 0x00020023)
	/* Wait NOP command for 400 nsec */
	POKE32(ST40_LMI_SCR_0(1), 0x00020021)
	POKE32(ST40_LMI_SCR_0(1), 0x00020021)
	POKE32(ST40_LMI_SCR_0(1), 0x00020021)
	POKE32(ST40_LMI_SCR_0(1), 0x00020021)
	POKE32(ST40_LMI_SCR_0(1), 0x00020021)
	POKE32(ST40_LMI_SCR_0(1), 0x00020021)
	POKE32(ST40_LMI_SCR_0(1), 0x00020021)
	POKE32(ST40_LMI_SCR_0(1), 0x00020021)
	POKE32(ST40_LMI_SCR_0(1), 0x00020021)
	POKE32(ST40_LMI_SCR_0(1), 0x00020021)

	/* Precharge all */
	POKE32(ST40_LMI_SCR_0(1), 0x00020022)
	/* Wait NOP command for 400 nsec */
	POKE32(ST40_LMI_SCR_0(1), 0x00020021)
	POKE32(ST40_LMI_SCR_0(1), 0x00020021)
	POKE32(ST40_LMI_SCR_0(1), 0x00020021)
	POKE32(ST40_LMI_SCR_0(1), 0x00020021)
	POKE32(ST40_LMI_SCR_0(1), 0x00020021)
	POKE32(ST40_LMI_SCR_0(1), 0x00020021)
	POKE32(ST40_LMI_SCR_0(1), 0x00020021)
	POKE32(ST40_LMI_SCR_0(1), 0x00020021)
	POKE32(ST40_LMI_SCR_0(1), 0x00020021)

	/* Issue EMRS2 */
	POKE32(ST40_LMI_SDMR0(1), 0x00010000)

	/* Issue EMRS3 */
	POKE32(ST40_LMI_SDMR0(1), 0x00018000)

	/* Issue EMRS1 to enable DLL */
	POKE32(ST40_LMI_SDMR0(1), 0x00008004)

	/* Issue MRS with DLL reset, CAS 5, Write recovery 6, Sequentiel, Burst lengh 8 */
	POKE32(ST40_LMI_SDMR0(1), 0x00000b53)

	/* Wait NOP command for 400 nsec */
	POKE32(ST40_LMI_SCR_0(1), 0x00020021)
	POKE32(ST40_LMI_SCR_0(1), 0x00020021)
	POKE32(ST40_LMI_SCR_0(1), 0x00020021)
	POKE32(ST40_LMI_SCR_0(1), 0x00020021)
	POKE32(ST40_LMI_SCR_0(1), 0x00020021)
	POKE32(ST40_LMI_SCR_0(1), 0x00020021)
	POKE32(ST40_LMI_SCR_0(1), 0x00020021)
	POKE32(ST40_LMI_SCR_0(1), 0x00020021)
	POKE32(ST40_LMI_SCR_0(1), 0x00020021)
	POKE32(ST40_LMI_SCR_0(1), 0x00020021)

	/* Precharge all */
	POKE32(ST40_LMI_SCR_0(1), 0x00020022)
	/* 2 CBR (auto refresh) */
	POKE32(ST40_LMI_SCR_0(1), 0x00020024)
	POKE32(ST40_LMI_SCR_0(1), 0x00020024)

	/* Issue MRS with CAS 5, Write recovery 6, Sequentiel, Burst lengh 8 */
	POKE32(ST40_LMI_SDMR0(1), 0x00000a53)

	/* Enable auto refresh */
	POKE32(ST40_LMI_MIM_0(1), 0x07f6035b)
	POKE32(ST40_LMI_SCR_0(1), 0x00020021)
	POKE32(ST40_LMI_SCR_0(1), 0x00020021)
	POKE32(ST40_LMI_SCR_0(1), 0x00020021)
	POKE32(ST40_LMI_SCR_0(1), 0x00020021)

	POKE32(ST40_LMI_GCC_0(1), 0x00000000)

#ifdef CONFIG_SH_SE_MODE
	/*
	 * Note that we also manually need to move the LMI0 and LMI1 base addresses to
	 * their 32-bit SE mode locations as defined in the datasheet and change the
	 * 'upper bound addresses' (in row attribute registers) for the LMIs.
	 */
	UPDATE_LONG(STX7200_SYSCONF_SYS_CFG38, 0xFFFFFF00, 0x00000040)
	UPDATE_LONG(STX7200_SYSCONF_SYS_CFG39, 0xFFFFFF00, 0x00000080)
	POKE_LONG(ST40_LMI_SDRA0_0(0), 0x50001a00)
	POKE_LONG(ST40_LMI_SDRA1_0(0), 0x50001a00)
	POKE_LONG(ST40_LMI_SDRA0_0(1), 0x90001a00)
	POKE_LONG(ST40_LMI_SDRA1_0(1), 0x90001a00)
#endif	/* CONFIG_SH_SE_MODE */

	END_MARKER

__memory_setup_table_end:

	.end
